package com.change.core.convert;

import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;

import java.text.DateFormat;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 通用的日期时间转换器
 *
 * @author linqunxun
 * @date 2021/9/10 10:24 上午
 */
public class GenericTimeConverter implements GenericConverter {

    private static DateFormat DATE_TIME_FORMAT = DateFormat.getDateTimeInstance();
    private static DateFormat DATE_FORMAT = DateFormat.getDateInstance();
    /**
     * 日期文本的最大长度
     */
    private final static int MAX_DATE_TEXT_LENGTH = 10;

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        Set<ConvertiblePair> pairSet = new HashSet<>();
        pairSet.add(new ConvertiblePair(String.class, LocalDateTime.class));
        pairSet.add(new ConvertiblePair(String.class, LocalDate.class));
        pairSet.add(new ConvertiblePair(String.class, LocalTime.class));
        pairSet.add(new ConvertiblePair(String.class, Date.class));
        return pairSet;
    }

    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        Class<?> sourceClass = sourceType.getType();
        Class<?> targetClass = targetType.getType();

        if (sourceClass == String.class) {
            String text = (String) source;
            if (targetClass == LocalDateTime.class) {
                return LocalDateTime.parse(text, DateFormatter.LOCAL_DATE_TIME);
            } else if (targetClass == LocalDate.class) {
                return LocalDate.parse(text, DateTimeFormatter.ISO_LOCAL_DATE);
            } else if (targetClass == LocalTime.class) {
                return LocalTime.parse(text, DateTimeFormatter.ISO_LOCAL_TIME);
            } else if (targetClass == Date.class) {
                try {
                    return (text.trim().length() > MAX_DATE_TEXT_LENGTH ? DATE_TIME_FORMAT : DATE_FORMAT).parse(text);
                } catch (ParseException e) {
                    throw new ConversionFailedException(sourceType, targetType, e.getMessage(), e);
                }
            }
        }

        throw new ConverterNotFoundException(sourceType, targetType);
    }

}
